package com.bsj.travel.monitor.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsj.travel.cached.redis.RedisCached;
import com.bsj.travel.def.common.DO.OtaUpgradeDO;
import com.bsj.travel.def.common.DTO.web.otaUpgrade.OtaUpgradeDTO;
import com.bsj.travel.def.common.DTO.web.otaUpgrade.OtaUpgradeSearchDTO;
import com.bsj.travel.def.common.VO.OtaUpgradeVO;
import com.bsj.travel.def.global.JsonResult;
import com.bsj.travel.def.global.JsonResultEnum;
import com.bsj.travel.exception.ApiException;
import com.bsj.travel.mapper.mysql.OtaUpgradeMapper;
import com.bsj.travel.mapper.mysql.ProductMapper;
import com.bsj.travel.monitor.service.OtaUpgradeService;
import com.bsj.travel.security.auth.AuthProduct;
import com.bsj.travel.util.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.FileStorageService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/***
 * @description OtaUpgradeServiceImpl
 * @author LiJiaXin
 * @version 1.0.0
 * @time 2024/1/26 17:00
 **/
@Service
public class OtaUpgradeServiceImpl implements OtaUpgradeService {

    @Resource
    private OtaUpgradeMapper otaUpgradeMapper;

    @Autowired
    private FileStorageService fileStorageService;

    @Resource
    private AuthProduct authProduct;

    @Resource
    private ProductMapper productMapper;

    @Autowired
    private RedisCached redisCached;

    /**
     * 添加OTA升级
     *
     * @param otaUpgradeDTO
     * @return com.bsj.travel.def.global.JsonResult
     * @author ljx
     * @time 2024/1/26 17:38
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult addOtaUpgrade(OtaUpgradeDTO otaUpgradeDTO) {
        paramCheck(otaUpgradeDTO);
        MultipartFile upgradePackage = otaUpgradeDTO.getUpgradePackage();
        String url = fileUpload(upgradePackage);
        //TODO 加密暂不处理
        OtaUpgradeDO otaUpgradeDO = new OtaUpgradeDO();
        BeanUtils.copyProperties(otaUpgradeDTO, otaUpgradeDO);
        String productKey = productMapper.selectById(otaUpgradeDTO.getProductId()).getProductKey();
        otaUpgradeDO.setProductKey(productKey);
        otaUpgradeDO.setUrl(url);
        otaUpgradeDO.setSize(upgradePackage.getSize());
        if (otaUpgradeMapper.insert(otaUpgradeDO) > 0) {
            redisCached.hsetOtaUpgradeInfo(productKey, otaUpgradeDO);
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 文件上传
     *
     * @param file
     * @return void
     * @author ljx
     * @time 2024/1/29 9:59
     */
    private String fileUpload(MultipartFile file) {
        FileInfo fileInfo = fileStorageService.of(file)
//                .setPath("upload/") //保存到相对路径下，为了方便管理，不需要可以不写
//                .setObjectId("0")   //关联对象id，为了方便管理，不需要可以不写
//                .setObjectType("0") //关联对象类型，为了方便管理，不需要可以不写
//                .putAttr("role", "admin") //保存一些属性，可以在切面、保存上传记录、自定义存储平台等地方获取使用，不需要可以不写
                .upload();  //将文件上传到对应地方
        if (fileInfo == null) {
            throw new ApiException(JsonResultEnum.UPGRADE_PACKAGE_UPLOAD_FAIL);
        }
        return fileInfo.getUrl();
    }

    /**
     * 参数校验
     *
     * @param otaUpgradeDTO
     * @return void
     * @author ljx
     * @time 2024/1/29 9:35
     */
    private void paramCheck(OtaUpgradeDTO otaUpgradeDTO) {
        String name = otaUpgradeDTO.getName();
        Long id = otaUpgradeDTO.getId();
        MultipartFile file = otaUpgradeDTO.getUpgradePackage();
        if (file == null || file.getSize() <= 0) {
            throw new ApiException(JsonResultEnum.FILE_IS_NULL);
        }
        authProduct.permissionCheck(otaUpgradeDTO.getProductId());
        QueryWrapper<OtaUpgradeDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", name);
        if (id != null) {
            queryWrapper.ne("id", id);
        }
        if (otaUpgradeMapper.exists(queryWrapper)) {
            throw new ApiException(JsonResultEnum.UPGRADE_PACKAGE_NAME_IS_NOT_NULL);
        }
    }

    /**
     * 删除OTA升级
     *
     * @param id
     * @return com.bsj.travel.def.global.JsonResult
     * @author ljx
     * @time 2024/1/26 17:38
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult deleteOtaUpgrade(Long id) {
        if (id == null) {
            return JsonResult.fail(JsonResultEnum.PARAM_ERROR);
        }
        OtaUpgradeDO oldOtaUpgradeDO = otaUpgradeMapper.selectById(id);
        if (oldOtaUpgradeDO == null) {
            return JsonResult.fail(JsonResultEnum.UPGRADE_PACKAGE_IS_NOT_EXIST);
        }
        authProduct.permissionCheck(oldOtaUpgradeDO.getProductId());
        if (otaUpgradeMapper.deleteById(id) > 0) {
            redisCached.hdelOtaUpgradeInfo(oldOtaUpgradeDO.getProductKey(), id);
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 修改OTA升级
     *
     * @param otaUpgradeDTO
     * @return com.bsj.travel.def.global.JsonResult
     * @author ljx
     * @time 2024/1/26 17:38
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult updateOtaUpgrade(OtaUpgradeDTO otaUpgradeDTO) {
        Long id = otaUpgradeDTO.getId();
        if (id == null) {
            return JsonResult.fail(JsonResultEnum.PARAM_ERROR);
        }
        OtaUpgradeDO oldOtaUpgradeDO = otaUpgradeMapper.selectById(id);
        if (oldOtaUpgradeDO == null) {
            return JsonResult.fail(JsonResultEnum.UPGRADE_PACKAGE_IS_NOT_EXIST);
        }
        paramCheck(otaUpgradeDTO);
        MultipartFile upgradePackage = otaUpgradeDTO.getUpgradePackage();
        String url = fileUpload(upgradePackage);
        OtaUpgradeDO otaUpgradeDO = new OtaUpgradeDO();
        BeanUtils.copyProperties(otaUpgradeDTO, otaUpgradeDO);
        String productKey = productMapper.selectById(otaUpgradeDTO.getProductId()).getProductKey();
        otaUpgradeDO.setProductKey(productKey);
        otaUpgradeDO.setUrl(url);
        otaUpgradeDO.setSize(upgradePackage.getSize());
        if (otaUpgradeMapper.updateById(otaUpgradeDO) > 0) {
            redisCached.hsetOtaUpgradeInfo(productKey, otaUpgradeDO);
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 根据id获取OTA升级信息
     *
     * @param id
     * @return com.bsj.travel.def.common.VO.OtaUpgradeVO
     * @author ljxd
     * @time 2024/1/26 17:38
     */
    @Override
    public OtaUpgradeVO getOtaUpgradeInfoById(Long id) {
        if (id == null) {
            throw new ApiException(JsonResultEnum.PARAM_ERROR);
        }
        OtaUpgradeDO otaUpgradeDO = otaUpgradeMapper.selectById(id);
        if (otaUpgradeDO == null) {
            throw new ApiException(JsonResultEnum.UPGRADE_PACKAGE_IS_NOT_EXIST);
        }
        authProduct.permissionCheck(otaUpgradeDO.getProductId());
        OtaUpgradeVO otaUpgradeVO = new OtaUpgradeVO();
        BeanUtils.copyProperties(otaUpgradeDO, otaUpgradeVO);
        return otaUpgradeVO;
    }

    /**
     * OTA升级分页
     *
     * @param otaUpgradeSearchDTO
     * @return com.bsj.travel.def.global.JsonResult<java.util.List < com.bsj.travel.def.common.VO.OtaUpgradeVO>>
     * @author ljx
     * @time 2024/1/26 17:39
     */
    @Override
    public JsonResult<List<OtaUpgradeVO>> pageOtaUpgrade(OtaUpgradeSearchDTO otaUpgradeSearchDTO) {
        IPage<OtaUpgradeDO> page = new Page<>(otaUpgradeSearchDTO.getPageNumber(), otaUpgradeSearchDTO.getPageSize());
        QueryWrapper<OtaUpgradeDO> queryWrapper = new QueryWrapper<>();
        String name = otaUpgradeSearchDTO.getName();
        Long productId = otaUpgradeSearchDTO.getProductId();
        if (StringUtils.isNotBlank(name)) {
            queryWrapper.eq("name", name);
        }
        if (productId != null) {
            authProduct.permissionCheck(productId);
            queryWrapper.eq("productId", productId);
        }
        queryWrapper.select("id", "name", "version", "productId", "createTime");
        List<OtaUpgradeVO> otaUpgradeVOS = new LinkedList<>();
        IPage<OtaUpgradeDO> iPage = otaUpgradeMapper.selectPage(page, queryWrapper);
        int total = (int) iPage.getTotal();
        if (total == 0) {
            return JsonResult.success(otaUpgradeVOS, total);
        }
        otaUpgradeVOS = iPage.getRecords().stream().map(otaUpgradeDO -> {
            OtaUpgradeVO otaUpgradeVO = new OtaUpgradeVO();
            BeanUtils.copyProperties(otaUpgradeDO, otaUpgradeVO);
            otaUpgradeVO.setCreateTime(DateUtils.parseDateToStr(otaUpgradeDO.getCreateTime()));
            return otaUpgradeVO;
        }).collect(Collectors.toList());
        return JsonResult.success(otaUpgradeVOS, total);
    }
}
